import Vue from 'vue';
const ctx = '@@InfiniteScroll'; //一个命名空间字符串
var throttle = function(fn, delay) {
    var now, lastExec, context, args, timer;
    var execute = function() {
        console.log("**************")
        fn.apply(context, args);
        lastExec = now;
    };
    return function() {
        context = this;
        args = arguments;
        now = Date.now();
        if (timer) {
            clearTimeout(timer);
            timer = null;
        }

        if (lastExec) {
            var diff = delay - (now - lastExec);
            if (diff < 0) {
                execute();
            } else {
                timer = setTimeout(() => {
                    execute();
                }, diff);
            }
        } else {
            execute();
        }
    }

}
var getScrollEventTarget = function(element) {
    var currentNode = element;
    // bugfix, see http://w3help.org/zh-cn/causes/SD9013 and http://stackoverflow.com/questions/17016740/onscroll-function-is-not-working-for-chrome
    while (currentNode && currentNode.tagName !== 'HTML' && currentNode.tagName !== 'BODY' && currentNode.nodeType === 1) {
        var overflowY = getComputedStyle(currentNode).overflowY;
        if (overflowY === 'scroll' || overflowY === 'auto') {
            return currentNode;
        }
        currentNode = currentNode.parentNode;
    }
    return window;
};
var getVisibleHeight = function(element) {
    if (element === window) {
        return document.documentElement.clientHeight;
    }

    return element.clientHeight;
};
var getScrollTop = function(element) {
    if (element === window) {
        return Math.max(window.pageYOffset || 0, document.documentElement.scrollTop);
    }

    return element.scrollTop;
};
var getElementTop = function(element) {
    if (element === window) {
        return getScrollTop(window);
    }
    return element.getBoundingClientRect().top + getScrollTop(window);
};

var doCheck = function(force) {
    var scrollEventTarget = this.scrollEventTarget;

    var element = this.el;
    var distance = this.distance;

    if (force !== true && this.disabled) return; //eslint-disable-line
    var viewportScrollTop = getScrollTop(scrollEventTarget);
    var viewportBottom = viewportScrollTop + getVisibleHeight(scrollEventTarget);

    var shouldTrigger = false;
    //console.log(element)
    // console.log(scrollEventTarget)
    if (scrollEventTarget === element) {
        shouldTrigger = scrollEventTarget.scrollHeight - viewportBottom <= distance;
    } else {
        var elementBottom = getElementTop(element) - getElementTop(scrollEventTarget) + element.offsetHeight + viewportScrollTop;
        console.log('绑定到WINDOW', elementBottom)
        shouldTrigger = Number(viewportBottom) + Number(distance) >= elementBottom;
        console.log(Number(viewportBottom) + Number(distance),elementBottom)
    }
    if (shouldTrigger && this.expression) {
        //v-infinite-scroll="loadMore" 值指向loadMore
        this.expression();
    }
};

function doBind() {
    const args = arguments;
    var directive = this;
    var element = directive.el;
    var distance = element.getAttribute('infinite-scroll-distance') ? element.getAttribute('infinite-scroll-distance') : 50;
    directive.distance = distance;
    directive.scrollEventTarget = getScrollEventTarget(element);
    directive.scrollListener = throttle(doCheck.bind(directive), 200);
    directive.scrollEventTarget.addEventListener('scroll', directive.scrollListener);


    var disabledExpr = element.getAttribute('infinite-scroll-disabled');
    var disabled = false;

    if (disabledExpr) {
    	//通过监听是否可以loading来触发"是否检测是否符合加载条件"
        this.vm.$watch(disabledExpr, function(value) {
            console.log("再次执行的是这里么")
            directive.disabled = value;
            if (!value ) {
                doCheck.call(directive);
            }
        });
        disabled = Boolean(directive.vm[disabledExpr]);
    }
    directive.disabled = disabled;
}

export default {
    bind(el, binding, vnode) {
            el[ctx] = {
                el,
                vm: vnode.context,
                expression: binding.value
            };
            const args = arguments;
            el[ctx].vm.$on('hook:mounted', function() {
                el[ctx].vm.$nextTick(function() {
                    doBind.call(el[ctx], args);
                });
            });

        },
        unbind(el) {

        }
}
